import 'dart:async';

import 'package:example/page/ext.dart';
import 'package:example/page/playground_page.dart';
import 'package:flujs/flujs.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;

import 'package:xterm/xterm.dart';

final baseCode = '''
function fib(n) {
  if (n == 0 || n == 1) return n;
  return fib(n - 1) + fib(n - 2);
}
fib(10);
''';

final jsCallNativeCode = '''
async function t() {
  const r = await runAsync();
  console.log('js: ' + r);
  return r;
}
1
''';

final intrinsicCode = '''
setTimeout(() => console.log('done!!!'), 3000);
console.log('hello, js world!');

setInterval(() => console.log('tictok!!!), 500);
''';

class BasicPage extends StatelessWidget {
  const BasicPage({super.key});

  @override
  Widget build(BuildContext context) {
    return PlaygroundPage(
      code: baseCode,
      title: 'Basic',
      controller: PlaygroundController(),
    );
  }
}

class JsCallNativePage extends StatefulWidget {
  const JsCallNativePage({super.key});

  @override
  State<JsCallNativePage> createState() => _JsCallNativePageState();
}

class _JsCallNativePageState extends State<JsCallNativePage> {
  final controller = PlaygroundController();
  @override
  void initState() {
    super.initState();
    controller
      ..jscGctx.addInterface('runAsync', _runAsync)
      ..qjsGctx.addInterface('runAsync', _runAsync)
      ..qjsCall = _jsCall
      ..jscCall = _jsCall;
  }

  void _jsCall(Terminal terminal, JSFContext ctx, String tag) {
    final tFunc = ctx.globalObject.getProperty('t');
    ctx.runPromise(tFunc).then((v) {
      terminal.writeln('[$tag] ${v.toString()}');
    }).catchError((e) {
      terminal.writeln('[$tag] error: ${e.toString()}');
    });
  }

  Future<num> _runAsync(args) async {
    var completer = Completer<num>();
    Timer(const Duration(seconds: 1), () {
      var n = math.Random().nextInt(100);
      controller.terminal.writeln('dart: runAsync return: $n');
      completer.complete(n);
    });
    return completer.future;
  }

  @override
  Widget build(BuildContext context) {
    return PlaygroundPage(
      code: jsCallNativeCode,
      title: 'JsCallNative',
      controller: PlaygroundController()
        ..jscGctx.addInterface('runAsync', _runAsync)
        ..qjsGctx.addInterface('runAsync', _runAsync),
      customOpts: [
        ElevatedButton(
            onPressed: () async {
              final t = controller.qjsGctx.globalObject.getProperty('t');
              var r = await controller.qjsGctx.runPromise(t);
              controller.terminal.writeln('[qjs:  dart -> js] ${r.toString()}');
            },
            child: Text('qjs: call js func in dart')),
        ElevatedButton(
            onPressed: () async {
              final t = controller.jscGctx.globalObject.getProperty('t');
              var r = await controller.jscGctx.runPromise(t);
              controller.terminal.writeln('[jsc: dart -> js] ${r.toString()}');
            },
            child: Text('jsc: call js func in dart')),
      ],
    );
  }
}

class IntrinsicPage extends StatelessWidget {
  const IntrinsicPage({super.key});

  @override
  Widget build(BuildContext context) {
    return PlaygroundPage(
      code: intrinsicCode,
      title: 'Intrinsic',
      controller: PlaygroundController(),
    );
  }
}
